﻿using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Micro.Extensions.Utilities;
using Microsoft.Extensions.Logging;

namespace Micro.Extensions.Data
{
    public class ConnectionProxy : DbConnection
    {
        private readonly DbConnection _dbConnection;
        private readonly ILogger _logger;
        private readonly int _executeSqlElapsedTimeWarning;
        private readonly bool _isLogEnable;
        public ConnectionProxy(DbConnection dbConnection,int executeSqlElapsedTimeWarning, ILogger logger)
        {
            _dbConnection = dbConnection;
            _logger = logger;
            _executeSqlElapsedTimeWarning = executeSqlElapsedTimeWarning;
            _isLogEnable = _logger.IsEnabled(LogLevel.Debug);
        }
        internal DbConnection GetRealDbConnection()
        {
            return _dbConnection;
        }
        protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel)
        {
            return _dbConnection.BeginTransaction(isolationLevel);
        }

        public override void ChangeDatabase(string databaseName)
        {
            _dbConnection.ChangeDatabase(databaseName);
        }

        public override void Close()
        {
            _dbConnection.Close();
        }

        public override void Open()
        {
            var sw = Stopwatch.StartNew();
            try
            {
                _dbConnection.Open();
            }
            finally
            {
                LogConnction(sw.ElapsedMilliseconds);
            }

        }

        public override async Task OpenAsync(CancellationToken cancellationToken)
        {
            var sw = Stopwatch.StartNew();
            try
            {
                await _dbConnection.OpenAsync(cancellationToken);
            }
            finally
            {
                LogConnction(sw.ElapsedMilliseconds);
            }

        }

        public override string ConnectionString { get => _dbConnection.ConnectionString; set => _dbConnection.ConnectionString = value; }
        public override string Database => _dbConnection.Database;
        public override ConnectionState State => _dbConnection.State;
        public override string DataSource => _dbConnection.DataSource;
        public override string ServerVersion => _dbConnection.ServerVersion;

        protected override DbCommand CreateDbCommand()
        {
            return new CommandProxy(_dbConnection.CreateCommand(), _executeSqlElapsedTimeWarning, _logger);
        }

        private void LogConnction(long elapsedMilliseconds)
        {
            //记录打开链接耗费时常超过预警值的
            if (elapsedMilliseconds > _executeSqlElapsedTimeWarning)
            {
                _logger.LogDataWarn(new 
                {
                    Opertaion= "Open Connection",
                    ConnectionString= ConnectionString,
                    TimeSpan = elapsedMilliseconds
                }.ToJson());
                return;
            }
            //只有在debug模式记录正常的打开操作
            if (_isLogEnable)
            {
                _logger.LogDataDebug(new
                {
                    Opertaion = "Open Connection",
                    ConnectionString = ConnectionString,
                    TimeSpan = elapsedMilliseconds
                }.ToJson());
            }

        }
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _dbConnection?.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}
